package com.ckzp.core.lc;

import java.util.Random;

/**
 * .
 */
public class Pwd {

    //密码必须是包含大写字母、小写字母、数字、特殊符号（不是字母，数字，下划线，汉字的字符）的8位以上组合
    public static final String PW_PATTERN_Aa1$8 = "^(?![A-Za-z0-9]+$)(?![a-z0-9\\W]+$)(?![A-Za-z\\W]+$)(?![A-Z0-9\\W]+$)[a-zA-Z0-9\\W]{8,}$";
    public static final String PW_PATTERN_Aa18 = "^(?![A-Za-z]+$)(?![a-z0-9]+$)(?![A-Z0-9]+$)[A-Za-z0-9]{8,}$";
    public static final String PW_PATTERN_a15 = "^[A-Za-z0-9]{5,}$";

    private static final String NUMBER_STR = "0123456789";
    private static final String LOWERCASE_LETTER_STR = "abcdefghijklmnopqrstuvwxyz";
    private static final String UPPERCASE_LETTER_STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    //private static final String SPECIAL_CHAR_STR = "~!@#$%^&*()_+-=`{}[]:;,./?\\\\|'\\\"\n\r\t ";
    private static final String SPECIAL_CHAR_STR = "!@#$%_";

    /**
     * 表达式表明：
     *
     * （1）^匹配开头

     　　　　（2）(?![A-Za-z0-9]+$)匹配后面不全是（大写字母或小写字母或数字）的位置，排除了（大写字母、小写字母、数字）的1种2种3种组合

     　　　　（3）(?![a-z0-9\\W]+$)同理，排除了（小写字母、数字、特殊符号）的1种2种3种组合

     　　　　（4）(?![A-Za-z\\W]+$)同理，排除了（大写字母、小写字母、特殊符号）的1种2种3种组合

     　　　　（5）(?![A-Z0-9\\W]+$)同理，排除了（大写字母、数组、特殊符号）的1种2种3种组合

     　　　　（6）[a-zA-Z0-9\\W]匹配（小写字母或大写字母或数字或特殊符号）因为排除了上面的组合，所以就只剩下了4种都包含的组合了

     　　　　（7）{8,}8位以上

     　　　　（8）$匹配字符串结尾
     */


    /**
     * 验证密码强度
     * <p/>
     * 包含大写字母、小写字母、数字、特殊符号（不是字母，数字，下划线，汉字的字符）的8位以上组合
     *
     * @param pwd
     * @return
     */
    public static boolean match_Aa1$8(String pwd) {
        if (pwd == null) return false;
        return pwd.matches(PW_PATTERN_Aa1$8);
    }


    /**
     * 验证帐号
     * <p/>
     * 包含数字或字符的5位以上组合
     *
     * @param pwd
     * @return
     */
    public static boolean match_a15(String pwd) {
        if (pwd == null) return false;
        return pwd.matches(PW_PATTERN_a15);
    }

    /**
     * 验证密码强度
     * <p/>
     * 包含大写字母、小写字母、数字的8位以上组合
     *
     * @param pwd
     * @return
     */
    public static boolean match_Aa18(String pwd) {
        if (pwd == null) return false;
        return pwd.matches(PW_PATTERN_Aa18);
    }


    /**
     * 随机密钥生成器
     * <p>Title         : generate lilinhai 2019年3月10日 下午12:42:33</p>
     *
     * @return String
     */
    public static final String getRandomPwd() {
        StringBuffer sb = new StringBuffer();
        sb.append(getRandomPwd(2, CharacterRange.UPPERCASE_LETTER_ONLY));
        sb.append(getRandomPwd(6, CharacterRange.LOWERCASE_LETTER_ONLY));
        sb.append(getRandomPwd(1, CharacterRange.SPECIAL_CHAR_ONLY));
        sb.append(getRandomPwd(3, CharacterRange.NUMBER_ONLY));
        return sb.toString();
    }


    /**
     * 随机密钥生成器
     * <p>Title         : generate lilinhai 2019年3月10日 下午12:42:33</p>
     *
     * @param length
     * @return String
     */
    public static final String getRandomPwd(int length) {
        return generate(length, CharacterRange.ALL.chars);
    }

    /**
     * 随机密钥生成器
     * <p>Title         : generate lilinhai 2019年3月10日 下午12:42:33</p>
     *
     * @param length
     * @return String
     */
    public static final String getRandomPwd(int length, CharacterRange characterRange) {
        return generate(length, characterRange.chars);
    }


    public static enum CharacterRange {
        /**
         * 仅仅只有数字字符
         */
        NUMBER_ONLY(NUMBER_STR),
        /**
         * 仅仅只有小写字母
         */
        LOWERCASE_LETTER_ONLY(LOWERCASE_LETTER_STR),
        /**
         * 仅仅只有大写字母
         */
        UPPERCASE_LETTER_ONLY(UPPERCASE_LETTER_STR),
        /**
         * 仅仅只有特殊字符
         */
        SPECIAL_CHAR_ONLY(SPECIAL_CHAR_STR),
        /**
         * 数字加小写
         */
        NUMBER_AND_LOWERCASE_LETTER(NUMBER_STR + LOWERCASE_LETTER_STR),
        /**
         * 数字加大小写
         */
        NUMBER_AND_LETTER(NUMBER_STR + LOWERCASE_LETTER_STR + UPPERCASE_LETTER_STR),
        /**
         * 所有字符
         */
        ALL(NUMBER_STR + LOWERCASE_LETTER_STR + UPPERCASE_LETTER_STR + SPECIAL_CHAR_STR);

        private CharacterRange(String charRange) {
            this.chars = charRange.toCharArray();
        }

        private char[] chars;
    }

    /**
     * 随机密钥生成器
     * <p>Title         : generate lilinhai 2019年3月10日 下午12:42:33</p>
     *
     * @param length
     * @return String
     */
    private static final String generate(int length, char[] chars) {
        Random random = new Random();
        shuffleTheCards(random, chars); // 洗牌
        StringBuilder keyBuilder = new StringBuilder();
        for (int i = 0; i < length; i++) {
            char c = chars[random.nextInt(chars.length)];
            if (c == '\n') {
                keyBuilder.append("\\n");
            } else if (c == '\t') {
                keyBuilder.append("\\t");
            } else if (c == '\r') {
                keyBuilder.append("\\r");
            } else if (c == '\"') {
                keyBuilder.append("\\\"");
            } else if (c == '\\') {
                keyBuilder.append("\\\\");
            } else {
                keyBuilder.append(c);
            }
        }
        return keyBuilder.toString();
    }


    /**
     * 洗牌
     * <p>Title         : shuffleTheCards lilinhai 2019年3月10日 下午12:37:09</p>
     * void
     */
    private static void shuffleTheCards(Random random, char[] chars) {
        for (int i = 0; i < chars.length; i++) {
            //生成随机数
            int j = random.nextInt(chars.length);
            //交换
            char temp = chars[i];
            chars[i] = chars[j];
            chars[j] = temp;
        }
    }

    public static void main(String[] arg) {
        System.out.println(getRandomPwd());
        System.out.println(getRandomPwd(12, CharacterRange.NUMBER_AND_LETTER));
        System.out.println(match_Aa18("BGrzrcer668"));
    }
}

